package com.rockblade.generator.utils;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.fill.Column;
import com.rockblade.generator.core.controller.BaseController;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author lost.yuan
 * @create 2022-07-11 14:30
 */
public class GeneratorUtils {

    /**
     * 表名集合
     */
    private List<String> tableNames = new ArrayList<>();

    private GeneratorUtils() {
    }

    private static class GeneratorUtilsInstance {
        private static final GeneratorUtils INSTANCE = new GeneratorUtils();
    }

    /**
     * 内部类单例
     *
     * @return 代码生成器工具类
     */
    public static GeneratorUtils getInstance() {
        return GeneratorUtils.GeneratorUtilsInstance.INSTANCE;
    }

    /**
     * 设置全局配置
     *
     * @param fastAutoGenerator
     * @param yamlReaderUtils
     */
    public void setGlobalConfig(FastAutoGenerator fastAutoGenerator, YamlReaderUtils yamlReaderUtils) {
        fastAutoGenerator.globalConfig(globalConfigBuilder -> globalConfigBuilder
                //覆盖已生成文件
                .fileOverride()
                //不打开生成文件目录
                .disableOpenDir()
                //输出搭配指定目录
                .outputDir((String) yamlReaderUtils.getValueByKey("generator.outputDir"))
                //注释作者
                .author((String) yamlReaderUtils.getValueByKey("generator.author"))
                //设置注释日期格式
                .commentDate((String) yamlReaderUtils.getValueByKey("generator.commentDate"))
                //使用Java8的时间类型
                .dateType(DateType.TIME_PACK));
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 设置包配置
     *
     * @param fastAutoGenerator
     * @param yamlReaderUtils
     */
    public void setPackageConfig(FastAutoGenerator fastAutoGenerator, YamlReaderUtils yamlReaderUtils) {
        fastAutoGenerator.packageConfig(packageConfigBuilder -> packageConfigBuilder
                .parent((String) yamlReaderUtils.getValueByKey("generator.packageName"))
                //.moduleName(MODULE_NAME)
                .entity("entity")
                .mapper("mapper")
                .service("service")
                .serviceImpl("service.impl")
                .controller("controller")
                .other("vo")
                .pathInfo(Collections.singletonMap(OutputFile.xml, (String) yamlReaderUtils.getValueByKey("generator.xmlPathInfo"))));
    }

    /**
     * 设置模板配置
     *
     * @param fastAutoGenerator
     */
    public void setTemplateConfig(FastAutoGenerator fastAutoGenerator) {
        fastAutoGenerator.templateConfig(templateConfig -> templateConfig
                .entity("/templates/java/domain.java")
                .service("/templates/java/service.java")
                .serviceImpl("/templates/java/serviceImpl.java")
                .mapper("/templates/java/mapper.java")
                .xml("/templates/xml/mapper.xml")
                .controller("/templates/java/controller.java"));

    }

    /**
     * 注入配置
     *
     * @param fastAutoGenerator
     * @param yamlReaderUtils
     */
    public void setStrategyConfig(FastAutoGenerator fastAutoGenerator, YamlReaderUtils yamlReaderUtils) {

        Map<String, String> otherTemplate = new HashMap<>(16);

        fastAutoGenerator.injectionConfig(injectionConfig -> injectionConfig
                .beforeOutputFile((tableInfo, objectMap) -> {
                    otherTemplate.clear();
                    otherTemplate.put(tableInfo.getEntityName() + "InfoForm.java", "/templates/java/infoForm.java.vm");
                    otherTemplate.put(tableInfo.getEntityName() + "InfoVo.java", "/templates/java/infoVo.java.vm");
                    otherTemplate.put(tableInfo.getEntityName() + "ListForm.java", "/templates/java/listForm.java.vm");
                    otherTemplate.put(tableInfo.getEntityName() + "ListVo.java", "/templates/java/listVo.java.vm");
                    //记录生成的表名
                    tableNames.add(tableInfo.getEntityName());
                })
                .customFile(otherTemplate));

        //5.策略配置
        fastAutoGenerator.strategyConfig(builder -> builder
                .enableCapitalMode()
                .enableSkipView()
                .disableSqlFilter()
                // 设置过滤表前缀
                .addTablePrefix((String) yamlReaderUtils.getValueByKey("generator.tablePrefix")));
        //6.Entity配置
        fastAutoGenerator.strategyConfig(strategyConfigBuilder -> strategyConfigBuilder
                        .entityBuilder()
                        //.superClass(BaseEntity.class)
                        //.enableChainModel()
                        .enableTableFieldAnnotation()
                        .naming(NamingStrategy.underline_to_camel)
                        .columnNaming(NamingStrategy.underline_to_camel)
                        .idType(IdType.ASSIGN_UUID)
                        .addTableFills(new Column("create_time", FieldFill.INSERT))
                        .addTableFills(new Column("update_time", FieldFill.INSERT_UPDATE))
                //.formatFileName("%sEntity")
        );
        //6.Controller配置
        fastAutoGenerator.strategyConfig(strategyConfigBuilder -> strategyConfigBuilder
                .controllerBuilder()
                .superClass(BaseController.class)
                .enableRestStyle());

        //7.Service配置
        fastAutoGenerator.strategyConfig(strategyConfigBuilder -> strategyConfigBuilder
                .serviceBuilder()
                .formatServiceFileName("%sService")
                .formatServiceImplFileName("%sServiceImpl"));

        //8.Mapper配置
        fastAutoGenerator.strategyConfig(strategyConfigBuilder -> strategyConfigBuilder
                .mapperBuilder()
                .enableMapperAnnotation()
                .formatMapperFileName("%sMapper")
                .formatXmlFileName("%sMapper")
                .enableBaseResultMap()
                .enableBaseColumnList());
    }

    /**
     * 移动Form类到指定文件夹中
     */
    public void moveFromFiles(YamlReaderUtils yamlReaderUtils) {
        //输出位置
        String packageName = (String) yamlReaderUtils.getValueByKey("generator.packageName");
        String packagePath = packageName.replace(".", "/");
        String outputDir = (String) yamlReaderUtils.getValueByKey("generator.outputDir");
        String formPath = outputDir + "/" + packagePath + "/form";
        String voPath = outputDir + "/" + packagePath + "/vo";
        File folder = new File(formPath);
        if (!folder.exists() && !folder.isDirectory()) {
            //创建Form文件夹
            folder.mkdirs();
        }
        //遍历表名
        tableNames.forEach(item -> {
            //创建表文件夹
            File tableFolder = new File(formPath + "/" + item);
            if (!tableFolder.exists() && !tableFolder.isDirectory()) {
                tableFolder.mkdirs();
            }
            try {
                //移动ListForm类
                File oldListFormFile = new File(voPath + "/" + item + "/" + item + "ListForm.java");
                FileUtils.copyFileToDirectory(oldListFormFile, tableFolder);
                FileUtils.forceDelete(oldListFormFile);
                //移动InfoForm类
                File oldInfoFormFile = new File(voPath + "/" + item + "/" + item + "InfoForm.java");
                FileUtils.copyFileToDirectory(oldInfoFormFile, tableFolder);
                FileUtils.forceDelete(oldInfoFormFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        });
        //清空表名
        tableNames.clear();
    }

}
